package com.lanbu.web.controller.camera;

import com.lanbu.common.config.LanBuConfig;
import com.lanbu.common.core.domain.AjaxResult;
import com.lanbu.common.utils.file.FileUploadUtils;
import com.lanbu.framework.config.ServerConfig;
import com.lanbu.system.utils.CustomMultipartFile;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import static com.lanbu.common.core.domain.AjaxResult.error;
import static com.lanbu.common.core.domain.AjaxResult.success;

@RestController
@RequestMapping("/system/camera")
public class PreviewCameraController {
    @Autowired
    private ServerConfig serverConfig;
    private static final int MAX_SEGMENT_COUNT = 999;

    @Value("${imgUrl.profile}")
    private String imgUrl;

    private Process ffmpegProcess = null;
    private ExecutorService executorService = Executors.newSingleThreadExecutor(); // 线程池


    @ApiOperation(value = "预览摄像头")
    @PostMapping("/start")
    public AjaxResult startStreaming(String rtspUrl,String ip) {

        String hlsOutputDirectory = imgUrl+"/upload/hls_output"+ip;
        // 确保目录存在
        File outputDir = new File(hlsOutputDirectory);
        if (!outputDir.exists()) {
            outputDir.mkdirs();
        }
        int maxSegmentNumber = getMaxSegmentNumber(hlsOutputDirectory); // 获取当前最大编号
        //  String segmentFilenamePattern = hlsOutputDirectory + "/segment_%03d.ts"; // Removed unused variable

        int startNumber;
        if (maxSegmentNumber >= MAX_SEGMENT_COUNT - 1) {
            startNumber = 0;
        } else {
            startNumber = maxSegmentNumber + 1;
        }



        // 构建 FFmpeg 命令
        List<String> command = new ArrayList<>();
//        command.add("ffmpeg");  // 使用系统的 FFmpeg 命令
        command.add("D:\\scripts\\ffmpeg-master-latest-win64-gpl\\bin\\ffmpeg.exe");
        command.add("-i");
        command.add(rtspUrl);
        command.add("-c:v");
        command.add("libx264");
        command.add("-c:a");
        command.add("aac");
        command.add("-f");
        command.add("hls");
        command.add("-hls_time");
        command.add("10");
        command.add("-hls_list_size");
        command.add("5"); // 限制播放列表中只保留最近的 5 个片段
        command.add("-start_number"); // 设置起始编号
        command.add(String.valueOf(startNumber)); // 使用计算出的起始编号
        command.add("-hls_segment_filename");
        command.add(hlsOutputDirectory + "/segment_%d.ts");  // 使用正确的格式化字符串
        command.add(hlsOutputDirectory + "/stream.m3u8");

        // 打印 FFmpeg 命令，便于调试
        System.out.println("ffmpeg Command: " + String.join(" ", command));

        // 使用 ExecutorService 启动一个线程来执行 FFmpeg 命令
        executorService.submit(() -> {
            try {
                // 使用 ProcessBuilder 执行 FFmpeg 命令
                ProcessBuilder processBuilder = new ProcessBuilder(command);
                processBuilder.redirectErrorStream(true);
                ffmpegProcess = processBuilder.start(); // 保存 FFmpeg 进程

                // 启动一个监控线程，负责检测并删除旧的 .ts 文件
                AtomicInteger segmentCounter = new AtomicInteger(0); // 计数器
                ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
                scheduler.scheduleAtFixedRate(() -> {
                    try {
                        // 每生成一个文件，检查并删除
                        int count = segmentCounter.incrementAndGet(); // 增加计数器
                        if (count >= 10) { // 达到 10 个文件时触发删除
                            deleteOldSegments(hlsOutputDirectory, 10);
                            segmentCounter.set(0); // 重置计数器
                        }
                    } catch (Exception e) {
                        System.err.println("Error during segment cleanup: " + e.getMessage());
                    }
                }, 0, 10, TimeUnit.SECONDS);

                // 获取 FFmpeg 执行过程中的输出信息
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(ffmpegProcess.getInputStream()))) {
                    String line;
                    while ((line = reader.readLine()) != null) {
                        System.out.println(line);  // 输出 FFmpeg 执行过程中的日志
                    }
                }

                // 等待 FFmpeg 命令执行完成
                int exitCode = ffmpegProcess.waitFor();
                if (exitCode == 0) {
                    // 上传 HLS 文件到服务器
                    uploadFilesToServer(hlsOutputDirectory);
                    System.out.println("HLS stream created and uploaded successfully.");
                } else {
                    System.err.println("FFmpeg process failed with exit code: " + exitCode);
                }
                scheduler.shutdown(); // 停止文件清理线程
            } catch (IOException | InterruptedException e) {
                System.err.println("Error occurred while processing FFmpeg command: " + e.getMessage());
                e.printStackTrace();
            }
        });

        return success("FFmpeg process started.");
    }
    // 方法：获取当前目录下的最大编号
    private int getMaxSegmentNumber(String directory) {
        int maxNumber = 0; // 初始化为 0
        File dir = new File(directory);
        File[] tsFiles = dir.listFiles((dir1, name) -> name.matches("segment_\\d{3}\\.ts")); // 匹配 segment_数字.ts 格式

        if (tsFiles != null) {
            for (File file : tsFiles) {
                // 提取文件名中的数字部分
                String fileName = file.getName();
                String numberStr = fileName.replaceAll("[^\\d]", ""); // 只保留数字部分
                try {
                    int number = Integer.parseInt(numberStr); // 转换为数字
                    if (number > maxNumber) {
                        maxNumber = number; // 更新最大值
                    }
                } catch (NumberFormatException e) {
                    System.err.println("Error parsing number from file name: " + fileName);
                }
            }
        }

        return maxNumber; // 返回最大编号
    }


    private void deleteOldSegments(String directory, int keepCount) {
        try {
            // 获取目录中的 .ts 文件列表
            File dir = new File(directory);
            File[] tsFiles = dir.listFiles((dir1, name) -> name.endsWith(".ts"));

            if (tsFiles != null && tsFiles.length > keepCount) {
                // 按文件的最后修改时间排序（最旧的文件排在最前面）
                Arrays.sort(tsFiles, Comparator.comparingLong(File::lastModified));

                // 删除多余的文件
                for (int i = 0; i < tsFiles.length - keepCount; i++) {
                    if (tsFiles[i].delete()) {
                        System.out.println("Deleted old segment: " + tsFiles[i].getName());
                    } else {
                        System.err.println("Failed to delete segment: " + tsFiles[i].getName());
                    }
                }
            }
        } catch (Exception e) {
            System.err.println("Error while deleting old segments: " + e.getMessage());
            e.printStackTrace();
        }
    }

    // 停止摄像头
    @ApiOperation(value = "停止摄像头")
    @PostMapping("/stop")
    public AjaxResult stopStreaming() {
        if (ffmpegProcess != null && ffmpegProcess.isAlive()) {
            System.out.println("Forcibly stopping FFmpeg process...");
            ffmpegProcess.destroyForcibly();  // 强制停止进程
            try {
                ffmpegProcess.waitFor();  // 等待进程完全停止
                System.out.println("FFmpeg process stopped forcibly.");
                return success("FFmpeg process stopped successfully.");
            } catch (InterruptedException e) {
                return error("Error while stopping FFmpeg process: " + e.getMessage());
            }
        }else {
            System.out.println("No active FFmpeg process to stop.");
            return success("No active FFmpeg process to stop.");
        }
    }

    // 上传文件到服务器
    private void uploadFilesToServer(String directoryPath) {
        File directory = new File(directoryPath);
        File[] files = directory.listFiles();

        if (files != null) {
            for (File file : files) {
                if (file.isFile()) {
                    uploadFile(file);
                }
            }
        }
    }

    // 上传单个文件
    private void uploadFile(File file) {
        byte[] fileContent = null;
        try {
            fileContent = Files.readAllBytes(file.toPath());

            CustomMultipartFile multipartFile = new CustomMultipartFile(
                    fileContent,
                    file.getName(),
                    file.getName(),
                    "text/plain"
            );
            // 上传文件路径
            String filePath1 = LanBuConfig.getUploadPath();
            // 上传并返回新文件名称
            String fileName1 = FileUploadUtils.upload(filePath1, multipartFile);

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


}
